/**
 * 
 */
package hu.gbalage.owl.editor.items.classes;

import hu.gbalage.owl.editor.OWLEditorManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLDescription;
import org.semanticweb.owl.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owl.model.OWLObjectIntersectionOf;
import org.semanticweb.owl.model.OWLOntology;
import org.semanticweb.owl.model.OWLSubClassAxiom;

/**
 * @author balage
 *
 */
public class ClassHierarchyTreeContentProvider implements ITreeContentProvider {
	
	OWLOntology ontology = null;
	
	Map<OWLClass, Set<OWLClass>> superclasses = new HashMap<OWLClass, Set<OWLClass>>();
	
	OWLEditorManager manager = null;
	
	private void fillClassInfo(){
		superclasses.clear();
		
		Set<OWLClass> clazzes = new HashSet<OWLClass>(ontology.getReferencedClasses());
		OWLClass thing = manager.getThing();
		clazzes.remove(thing);
		
		//fill superclasses
		for(OWLClass clazz : clazzes){
			Set<OWLClass> supc = new HashSet<OWLClass>();
			superclasses.put(clazz, supc);
			for(OWLSubClassAxiom a : ontology.getSubClassAxiomsForLHS(clazz)){
				OWLDescription d = a.getSuperClass();
				if (!d.isAnonymous())
					supc.add(d.asOWLClass());
			}
			for(OWLEquivalentClassesAxiom a : ontology.getEquivalentClassesAxioms(clazz)){
				//System.out.println(clazz+" equivalent with: ");
				for(OWLDescription d : a.getDescriptions()){
					if (d instanceof OWLObjectIntersectionOf){
						OWLObjectIntersectionOf io = (OWLObjectIntersectionOf)d;
						for(OWLDescription u : io.getOperands()){
							if(!u.isAnonymous()) supc.add(u.asOWLClass());
						}
					}
					//System.out.println(d.toString()+" ("+d.getClass()+")");
				}
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
	 */
	public Object[] getChildren(Object parentElement) {
		OWLClass thing = manager.getThing();
		List<OWLClass> clss = new ArrayList<OWLClass>();
		
		if (thing.equals(parentElement)){
			for(OWLClass cls : superclasses.keySet()){
				if (superclasses.get(cls).isEmpty()) clss.add(cls);
			}
		}else{	
			for(OWLClass cls : superclasses.keySet()){
				if (superclasses.get(cls).contains(parentElement)) clss.add(cls);
			}
		}
		return clss.toArray();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
	 */
	public Object getParent(Object element) {
		return superclasses.get(element).iterator().next();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
	 */
	public boolean hasChildren(Object element) {
		return manager.getThing().equals(element) || getChildren(element).length > 0;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
	 */
	public Object[] getElements(Object inputElement) {
		if (manager == null) return new Object[]{};
		return new Object[]{manager.getThing()};
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
	 */
	public void dispose() {
		

	}

/*	public ClassHierarchyTreeContentProvider(OWLEditorManager manager){
		this.manager = manager;
		ontology = manager.getOntology();
		fillClassInfo();
	}
*/	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
	 */
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		
		if (newInput instanceof OWLEditorManager){
			manager = (OWLEditorManager)newInput;
			ontology = manager.getOntology();
			fillClassInfo();
		}

	}

}
